package com.csx.micrometer.discovery.adapter;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;
import com.csx.micrometer.discovery.config.MicrometerDiscoveryProperties;
import com.csx.micrometer.discovery.constant.NacosOpenApiConstants;
import com.csx.micrometer.common.constant.OpenApiConstants;
import com.csx.micrometer.discovery.annotation.RegistryCenter;
import com.csx.micrometer.discovery.annotation.RegistryCenterTypeEnum;
import com.csx.micrometer.discovery.model.InstanceDetailPojo;
import com.csx.micrometer.discovery.model.NamespaceDetail;
import com.csx.micrometer.discovery.model.NamespaceListPojo;
import com.csx.micrometer.discovery.model.ServicePojo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;

/**
 * @author cuisongxu
 * @date 2022/12/5 18:20
 */
@Component
@RegistryCenter(type = RegistryCenterTypeEnum.NACOS)
public class NacosRegistryCenterServiceImpl implements RegistryCenterService{

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private MicrometerDiscoveryProperties micrometerDiscoveryProperties;

    @Override
    public List<NamespaceDetail> getNamespaces() {
        // 查询所有的命名空间
        String namespaceUrl = OpenApiConstants.HTTP_PREFIX + micrometerDiscoveryProperties.getAddress() + NacosOpenApiConstants.GET_ALL_NAMESPACE_URI;
        ResponseEntity<String> stringResponseEntity = restTemplate.exchange(namespaceUrl, HttpMethod.GET, new HttpEntity<>(null, null), String.class);
        NamespaceListPojo namespaceListPojo = JSON.parseObject(stringResponseEntity.getBody(), NamespaceListPojo.class);
        assert namespaceListPojo != null;
        return namespaceListPojo.getData();
    }

    @Override
    public List<ServicePojo> getServices(NamespaceDetail namespaceDetail) {
        if(ObjectUtils.isEmpty(namespaceDetail)) {
            return new ArrayList<>();
        }
        Properties properties = new Properties();
        properties.setProperty("namespace", namespaceDetail.getNamespace());
        properties.setProperty("serverAddr", micrometerDiscoveryProperties.getAddress());
        try {
            NamingService namingService = NacosFactory.createNamingService(properties);
            ListView<String> servicesOfServer = namingService.getServicesOfServer(1, 99999999);
            if(servicesOfServer == null || servicesOfServer.getData() == null) {
             return new ArrayList<>();
            }
            return servicesOfServer.getData().stream().map(service -> {
                ServicePojo servicePojo = new ServicePojo();
                servicePojo.setName(service);
                return servicePojo;
            }).collect(Collectors.toList());

        } catch (NacosException e) {
            e.printStackTrace();
        }
        return new ArrayList<>();
    }

    @Override
    public List<InstanceDetailPojo> getInstances(String namespace, ServicePojo servicePojo) {
        if(ObjectUtils.isEmpty(namespace) || ObjectUtils.isEmpty(servicePojo)) {
            return new ArrayList<>();
        }
        Properties properties = new Properties();
        properties.setProperty("namespace", namespace);
        properties.setProperty("serverAddr", micrometerDiscoveryProperties.getAddress());
        try {
            NamingService namingService = NacosFactory.createNamingService(properties);
            List<Instance> allInstances = namingService.getAllInstances(servicePojo.getName());

            return allInstances.stream().map(instance -> {
                InstanceDetailPojo instanceDetailPojo = new InstanceDetailPojo();
                BeanUtils.copyProperties(instance, instanceDetailPojo);
                return instanceDetailPojo;
            }).collect(Collectors.toList());

        }catch (NacosException e) {
            e.printStackTrace();
        }
        return new ArrayList<>();
    }
}
